

######################## 
<# 
.SYNOPSIS 
 Searches for and changes IM Addresses within a single mailbox or a scope of Mailboxes actions completed by using the the Exchange Web Services API 
 
.DESCRIPTION 
 Searches for and changes IM Addresses within a single mailbox or a scope of Mailboxes actions completed by using the the Exchange Web Services API 
  
  Requires the EWS Managed API from https://www.microsoft.com/en-us/download/details.aspx?id=42951
  If using the get mail 

.EXAMPLE
	
	Example 1 To Remove all IMAddresses for all contacts within a single mailbox also enables extra logging
	Update-MailboxConacts -Identity postmaster@email.com -SetToNull -Verbose

	Example 2 To Remove all IMAddresses for all contacts for a number of mailbox in a single OU
	Get-Mailbox -OrganizationalUnit corp.domain.com/users | Update-MailboxConacts -SetToNull

	Example 3 Set to Null all contacts with a IMAddress containing email.com in the IMAddress field within a single mailbox
	Update-MailboxConacts -Identity postmaster@email.com -SearchQuery "*email.com" -SetToNull

    GOTCHA: This will also affect any IMAddresses using subdomains like sub.email.com

	Example 4 Update contacts with a IMAddress of email.com in the IMAddress to newdomain.com
	Update-MailboxConacts -Identity postmaster@email.com -SearchQuery "*email.com" -NewDomain "newdomain.com"

    GOTCHA: This will also affect any IMAddresses using subdomains like sub.email.com

	This cmdlet uses the EmailAddress as unique key via a string or (get-mailbox jjbin0).windowsemailaddress
   .Notes 
    NAME:  Set Mailbox's Contacts via EWS
    AUTHOR: Joshua Bines 
    LASTEDIT: 29/02/2016 

Change Log
*******************
20160229 - jjbin0 Script Created

#> 
#########################
function Set-MailboxContacts
{ 
    [CmdletBinding()] 
    param( 
    	[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] $Identity,
		[Parameter(Position=1, Mandatory=$false)] [string]$SearchQuery = "*",
        [Parameter(Position=2, Mandatory=$false)] [bool]$impersonate = $true,
		[Parameter(Position=3, Mandatory=$false)] [string]$NewDomain,
		[Parameter(Position=4, Mandatory=$false)] [switch]$SetToNull
		
    ) 

Begin {
        Write-Verbose "Initialize stuff in Begin block"
        Write-Verbose "SearchQuery set to $($SearchQuery)"
        Write-Verbose "Impersonate set to $($impersonate)"
        
        Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"

        $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService

    }

Process {
        Write-Verbose "Process block"

        #Obstract email string from array or pass directly to $mailbox var
        if(!($Identity -is [string])){
        
                Write-Verbose "IFSTATE"; $Mailbox = @($Identity).windowsemailaddress
                
                }
            
            else{
            
                Write-Verbose "IFELSESTATE";$Mailbox = $Identity
            
                }


#Bind to Exchange Webservices 

            $ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId -ArgumentList ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress),$Mailbox
            $service.ImpersonatedUserId = $ImpersonatedUserId
            $service.AutodiscoverUrl($Mailbox)
            Write-Host $Mailbox -ForegroundColor Green

#Find Contact Folders

            $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$Mailbox)
            $tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)  
            $fldClass = "IPF.Contact"

	        #Perform search based on the displayname of each folder level 
	        $fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(100) 
            $fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep;            
	        $SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::FolderClass,$fldClass) 
	        $findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfsearchFilter,$fvFolderView) 

             Write-Verbose "Total Contact folders found $($findFolderResults.totalcount)"

#Find Contact Objects within Contact folders

        $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView -ArgumentList 10000
		
        $propertyset = New-Object Microsoft.Exchange.WebServices.Data.PropertySet ([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly)

        #$Item_SearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ContactSchema]::IMAddress1,$IM_search) 
        $propIM1 = [Microsoft.Exchange.WebServices.Data.ContactSchema]::IMAddress1
        $Item_SearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+Exists($propIM1) 
        $view.PropertySet = $propertyset

    foreach($folder in $findFolderResults){
            $items = $service.FindItems($Folder.id,$Item_SearchFilter,$view)
            Write-Verbose "Total Contact objects found $($items.totalcount)"
             

             #$items |?{$items -ne $null}| ForEach-Object
             
             foreach($contact in $items){ 
                          Try{
                                  
                                  $item= [Microsoft.Exchange.WebServices.Data.Contact]::Bind($service, $contact.Id);
                                  
                            }
                          catch{
                                  #Catch some invaild contacts which do not match
                                  Write-Warning "$_"
                                }
                          if((($item.IMAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress1]) -like $SearchQuery)-and($item.IMAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress1]) -ne $null){
                               
                               $item_IM1 = "$($item.IMAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress1])"
                               $item_IM2 = "$($item.IMAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress2])"
                               Write-Host "      "
                               Write-Host "Contact Object"
                               Write-Host "      First Name:" -NoNewline; Write-host $item.GivenName -ForegroundColor Yellow          
                               Write-Host "      Surname:"-NoNewline; Write-host $item.Surname -ForegroundColor Yellow             
                               Write-Host "      IM 1:" -NoNewline; Write-host $item_IM1 -ForegroundColor Yellow
                               Write-Host "      IM 2:" -NoNewline; write-host $item_IM2 -ForegroundColor Yellow

                            if($NewDomain){
                              Write-Verbose "Setting Contact item to new IM1 Domain"

                                if($item_IM1 -like'*@*'){
                                   $item_IM1Split = ($item.IMAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress1]).Split("@")

                                   $item_IM1SplitFirst = $item_IM1Split[0]

                                   Write-Verbose "Setting IM Address"
                                   
                                    if($item_IM1 -notmatch "$($item_IM1SplitFirst)@$NewDomain"){
                                        Write-Verbose "Setting new IMAddress1 $($item_IM1SplitFirst)@$NewDomain"
                                        try{
                                            $item.ImAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress1] = "$($item_IM1SplitFirst)@$NewDomain"
                                            $item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
                                            if($?){Write-Host "Updated IM1 to $($item_IM1SplitFirst)@$NewDomain Successfully" -ForegroundColor Yellow}
                                            }
                                        
                                        catch{
                                            Write-Warning $_
                                            }


                                    }
                                  
                                  else{Write-Warning "No Change IM Address already set to $($item_IM1SplitFirst)@$NewDomain"}

                                }
                               
                                if($item_IM2 -like '*@*'){
                              Write-Verbose "Setting Contact item to new IM2 Domain"

                                if($item_IM2 -ne $null){
                                   $item_IM2Split = ($item.IMAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress2]).Split("@")

                                $item_IM2SplitFirst = $item_IM2Split[0]

                                   Write-Verbose "Setting IM Address"

                                    if($item_IM2 -notmatch "$($item_IM2SplitFirst)@$NewDomain"){
                                        Write-Verbose "Setting new IMAddress1 $($item_IM2SplitFirst)@$NewDomain"
                                        try{
                                            $item.ImAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress2] = "$($item_IM2SplitFirst)@$NewDomain"
                                            $item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
                                            if($?){Write-Host "Updated IM2 to $($item_IM2SplitFirst)@$NewDomain Successfully" -ForegroundColor Yellow}
                                            }
                                        
                                        catch{
                                            Write-Warning $_
                                            }

                                    }
                                    else{Write-Warning "No Change IM Address already set to $($item_IM2SplitFirst)@$NewDomain"}

                                    }
                                }


                              
                                }#EndIf
                            
                            if($SetToNull){
                                Write-Verbose "Setting Contact item to NULL"
                               $item.ImAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress1] = $null
                               $item.ImAddresses[[Microsoft.Exchange.WebServices.Data.IMAddressKey]::ImAddress2] = $null
                               $item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
                               if($?){Write-Host "Set IM Addresses Successfully to NULL" -ForegroundColor Yellow}

                               }
                           }
                
                    }

        }
     
    }#Process

End {
        Write-Verbose "Final work in End block"

    }#End

}